package com.zj.weather.bgviews.light;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;

import java.util.ArrayList;
import java.util.List;

import com.zj.weather.R;
import com.zj.weather.base.BaseHolder;
import com.zj.weather.base.BaseWeatherBgView;
import com.zj.weather.base.HoldersInfo;
import com.zj.weather.bgviews.RainDrawer;
import com.zj.weather.bgviews.light.child.LargeLightInfo;
import com.zj.weather.bgviews.light.child.MiddleLight;
import com.zj.weather.bgviews.light.child.SmallLightInfo;

import static com.zj.weather.utils.RandomUtils.getRandom;

/**
 * Created by zhaojie on 2017/9/14.
 */
public class LightDrawer extends BaseWeatherBgView {

    private static final int RAIN_COUNT = 320;
    private static final int lightCongruence = 7;

    public LightDrawer(Context context) {
        super(context);
    }

    @Override
    protected List<HoldersInfo> getHolders() {
        List<HoldersInfo> infos = new ArrayList<>();
        infos.add(new HoldersInfo(RAIN_COUNT) {
            @Override
            public RainDrawer.RainHolder getHolderType(int position) {
                return new RainDrawer.RainHolder(width, height, position, 2500f);
            }
        });
        infos.add(new HoldersInfo(1) {
            @Override
            public CloudHolder getHolderType(int position) {
                return new CloudHolder(width, height, position);
            }
        });
        return infos;
    }

    public static class CloudHolder extends BaseHolder {
        private boolean isShowLight = false;
        private Drawable drawable;
        private float percentWidthPerframe = 0.0003f;
        private float drawableWidth, drawableHeight;
        private float curX;
        private float minX, maxX;
        private boolean isPost = true;
        private LightHolder lightHolder;

        public CloudHolder(float w, float h, int i) {
            super(w, h, i);
        }

        private int curPosition = 0;

        private boolean updateParams(boolean isShowLight) {
            boolean isShow = false;
            float curOffset = percentWidthPerframe * drawableWidth * getRandom(0.5f, 1);
            if (isPost) {
                curX -= curOffset;
                if (curX < minX) {
                    isPost = false;
                }
            } else {
                curX += curOffset;
                if (curX >= maxX) {
                    isPost = true;
                }
            }
            if (!isShowLight) {
                int curPosition = (int) (Math.abs(curX / minX) * 100f);
                isShow = (curPosition % lightCongruence == 0 && curPosition != this.curPosition);
                if (isShow) this.curPosition = curPosition;
            }
            return isShow;
        }

        @Override
        public void initData(Context context) {
            this.drawable = context.getResources().getDrawable(R.mipmap.overcast);
            this.drawableWidth = canvasWidth * 1.2f;
            float scale = 0.375f;
            this.drawableHeight = drawableWidth * scale;
            lightHolder = new LightHolder(drawableHeight, canvasWidth, canvasHeight);
            minX = this.canvasWidth - this.drawableWidth;
            maxX = 0f;
            this.curX = getRandom(minX, 0);
        }

        @Override
        public void updateFrame(Context context, Canvas canvas, float changedAlpha) {
            boolean isShow = updateParams(isShowLight);
            if (isShow || isShowLight) {
                isShowLight = !lightHolder.updateAndDraw(canvas, context, changedAlpha);
            }
            final int left = Math.round(curX);
            drawable.setBounds(left, 0, Math.round(left + drawableWidth), Math.round(drawableHeight));
            drawable.setAlpha((int) (changedAlpha * 255f));
            drawable.draw(canvas);
        }
    }

    public static class LightHolder {
        private final float width, height;
        private final float cloudHeight;

        public LightHolder(float cloudHeight, float width, float height) {
            this.cloudHeight = cloudHeight;
            this.width = width;
            this.height = height;
        }

        boolean updateAndDraw(Canvas canvas, Context context, float changedAlpha) {
            return drawLighting(context, canvas, changedAlpha);
        }

        /**
         * 闪电的类型 「 0- 基础，云层下方闪烁光团」
         * 「1 阶梯放电，方向随机，无火花，0-3个分叉，2-6个子分叉，屏幕伴随0x20 alpha的快速闪烁」
         * 「2 贯穿雷 ，顶部到底部，画出雷触，5-10个分叉，无子分叉，首个雷触分叉到达底部后触发贯穿雷暴，屏幕伴随0x90 alpha的快速连续闪烁」
         */
        private int code;
        private LightInfo info;

        /**
         * @param context
         * @param canvas
         * @param changeAlpha
         * @return 当前绘制是否完成，返回true 则完成；
         */
        private boolean drawLighting(Context context, Canvas canvas, float changeAlpha) {
            boolean isFinishLighting = false;
            if (info == null) {
                switch (code) {
                    case 0:
                        info = drawSmallLight();
                        break;
                    case 1:
                        info = drawSmallLight();
                        break;
                    case 2:
                        info = drawMiddleLight();
                        break;
                    case 3:
                        info = drawSmallLight();
                        break;
                    case 4:
                        info = drawMiddleLight();
                        break;
                    case 5:
                        info = drawSmallLight();
                    case 6:
                        info = drawSmallLight();
                        break;
                    case 7:
                        info = drawMiddleLight();
                        break;
                    case 8:
                        info = drawSmallLight();
                        break;
                    case 9:
                        info = drawMiddleLight();
                        break;
                    case 10:
                        info = drawLargeLight();
                        break;
                    case 11:
                        info = drawSmallLight();
                        break;
                    case 12:
                        info = drawMiddleLight();
                        break;
                    default:
                        code = 0;
                        return true;
                }
                info.initData(context);
            }
            if (info != null) {
                isFinishLighting = info.draw(context, canvas, changeAlpha);
            }
            if (isFinishLighting) {
                code++;
                info = null;
            }
            return isFinishLighting;
        }

        private LightInfo drawSmallLight() {
            return new SmallLightInfo(width, height, cloudHeight, 1.0f, 1.0f, 0, 8);
        }

        private LightInfo drawLargeLight() {
            return new LargeLightInfo(width, height, cloudHeight, 1.0f, 0.13f, 0, 5);
        }

        private LightInfo drawMiddleLight() {
            return new MiddleLight(width, height, cloudHeight, 1.0f, 0, 10, 3);
        }
    }
}

